package aupdg.presentation;

import aupdg.data.model.impl.AuDataDependenceEdge;
import aupdg.logic.analysis.SecurityLevel;
import aupdg.presentation.NodePopupMenu.HighLevNodeRadioButton;
import aupdg.presentation.NodePopupMenu.LowLevNodeRadioButton;
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.JPopupMenu;

/**
 * This class implements the mechanism for manipulating and controlling a graph
 * visualization, in terms of a mouse plug-in.
 *
 * @param <Node>
 * @param <Edge>
 * @author AA and CJ
 */
public class NodeEdgePopupMousePlugin<Node, Edge> extends AbstractPopupGraphMousePlugin {

    /**
     * Menu to show when an edge is right clicked.
     */
    private JPopupMenu edgeMenu;
    /**
     * Menu to show when a node is right clicked.
     */
    private JPopupMenu nodeMenu;

    /**
     * Default constructor.
     */
    public NodeEdgePopupMousePlugin() {
        this(MouseEvent.BUTTON3_MASK);
    }

    /**
     *
     * @param modifiers
     */
    public NodeEdgePopupMousePlugin(int modifiers) {
        super(modifiers);
    }

    @Override
    protected void handlePopup(MouseEvent e) {
        final VisualizationViewer<Node, Edge> vv = (VisualizationViewer<Node, Edge>) e.getSource();
        GraphElementAccessor<Node, Edge> pickSup = vv.getPickSupport();
        Point2D point = e.getPoint();
        if (pickSup != null) {
            final Node n = pickSup.getVertex(vv.getGraphLayout(), point.getX(), point.getY());
            if (n != null) {
                System.out.println("Node " + n + " was right clicked");
                updateNodeMenu(n, vv, point);
                this.nodeMenu.show(vv, e.getX(), e.getY());
            } else {
                final Edge edge = pickSup.getEdge(vv.getGraphLayout(), point.getX(), point.getY());
                if (edge != null && edge instanceof AuDataDependenceEdge) {
                    System.out.println("Edge " + edge + " was right clicked");
                    updateEdgeMenu((AuDataDependenceEdge) edge, vv, point);
                    this.edgeMenu.show(vv, e.getX(), e.getY());
                }
            }
        }
    }

    /**
     * Returns the menu to be shown when the user right-clicks on an edge.
     *
     * @return
     */
    public JPopupMenu getEdgeMenu() {
        return this.edgeMenu;
    }

    /**
     * Sets the menu to be shown when the user right-clicks on an edge.
     *
     * @param edgeMenu
     */
    public void setEdgeMenu(JPopupMenu edgeMenu) {
        this.edgeMenu = edgeMenu;
    }

    /**
     * Returns the menu to be shown when the user right-clicks on a node.
     *
     * @return
     */
    public JPopupMenu getNodeMenu() {
        return this.nodeMenu;
    }

    /**
     * Sets the menu to be shown when the user right-clicks on a node.
     *
     * @param nodeMenu
     */
    public void setNodeMenu(JPopupMenu nodeMenu) {
        this.nodeMenu = nodeMenu;
    }

    /**
     * Sets the right node and view in EdgeMenuListener, so that the graph can
     * be updated.
     *
     * @param n
     * @param vv
     * @param point
     */
    public void updateNodeMenu(Node n, VisualizationViewer vv, Point2D point) {
        if (this.getNodeMenu() == null) {
            return;
        } else {
            Component[] mnuComponents = this.getNodeMenu().getComponents();
            for (Component c : mnuComponents) {
                if (c instanceof NodeMenuListener) {
                    ((NodeMenuListener) c).setNode(n);
                    ((NodeMenuListener) c).setView(vv);
                }
                if (c instanceof HighLevNodeRadioButton && ((aupdg.data.model.Node) n).getLevel() == SecurityLevel.HIGH) {
                    ((HighLevNodeRadioButton) c).setSelected(true);
                }
                if (c instanceof LowLevNodeRadioButton && ((aupdg.data.model.Node) n).getLevel() == SecurityLevel.LOW) {
                    ((LowLevNodeRadioButton) c).setSelected(true);
                }
            }
        }
    }

    /**
     * Sets the right edge and view in EdgeMenuListener, so that the graph can
     * be updated.
     *
     * @param e
     * @param vv
     * @param point
     */
    public void updateEdgeMenu(AuDataDependenceEdge e, VisualizationViewer vv, Point2D point) {
        if (this.getEdgeMenu() == null) {
            return;
        } else {
            if (this.getEdgeMenu() instanceof EdgeMenuListener) {
                System.out.println("Updating Edge ");
                ((EdgeMenuListener) this.getEdgeMenu()).setEdge(e);
                ((EdgeMenuListener) this.getEdgeMenu()).setView(vv);
            }
        }
    }
}
